﻿#include "FXProtocol.h"
#include <QRegularExpression>
#pragma execution_character_set("utf-8")

FXProtocol::FXProtocol(const QString& name, QObject *parent)
    : PLCClientBase(name, parent)
{
    mConfig.type = PCT_FX;
    mSerialClient = new SerialCom(this);
    mSerialClient->setReconnectEnable(false);
    connect(mSerialClient, &SerialCom::sigReceiveData, this, &FXProtocol::onReceiveData);
    connect(mSerialClient, &SerialCom::sigStateChanged, this, &FXProtocol::onStateChanged);
}
FXProtocol::~FXProtocol()
{
    if(mSerialClient)
        mSerialClient->onQuit();
}
void FXProtocol::onStateChanged(ComState socketState)
{
    setPLCState(socketState);
}
void FXProtocol::initCom()
{
    if(!mSerialClient)
        return;
    mSerialClient->setConfig(mConfig.comConfig);
    mSerialClient->onInit();
}
void FXProtocol::sendReadData(const PLCRequestData &data)
{
    mCurDataRead = data;
    QString command;
    switch(mCurDataRead.table){
    case QModbusDataUnit::HoldingRegisters:
        command = getReadHoldRegisterCommand(mCurDataRead.addrStart, mCurDataRead.getAddrSize());
        break;
    case QModbusDataUnit::Coils:
        command = getReadCoilsRegisterCommand(mCurDataRead.addrStart, mCurDataRead.getAddrSize());
        break;
    case QModbusDataUnit::InputRegisters:
        command = getReadCoilsRegisterCommand(mCurDataRead.addrStart, mCurDataRead.getAddrSize());
        break;
    default:
        break;
    }
    mSerialClient->onWrite(command);
}

void FXProtocol::sendWriteData(const PLCRequestData &data)
{
    mCurDataWrite = data;
    QString command;
    switch(mCurDataWrite.table){
    case QModbusDataUnit::HoldingRegisters:
        command = getWriteHoldRegisterCommand(mCurDataWrite.addrStart, mCurDataWrite.getAddrSize(), mCurDataWrite.data);
        break;
    case QModbusDataUnit::Coils:
        command = getWriteCoilsRegisterCommand(mCurDataWrite.addrStart, mCurDataWrite.getAddrSize(), mCurDataWrite.data);
        break;
    default:
        break;
    }
    mSerialClient->onWrite(command);
}

QString FXProtocol::addrNumStr(int startAddr,int num)
{
    QString sendstr="";
    //起始地址
    QByteArray array0,array1;
    array0=QString("%1").arg(startAddr,4,10,QLatin1Char('0')).toUpper().toLatin1();
    array1.resize(1);
    array1[0]=array0.at(0);
    sendstr+=array1.toHex();
    array1[0]=array0.at(1);
    sendstr+=array1.toHex();
    array1[0]=array0.at(2);
    sendstr+=array1.toHex();
    array1[0]=array0.at(3);
    sendstr+=array1.toHex();
    //数据长度
    array0=QString("%1").arg(num,2,16,QLatin1Char('0')).toUpper().toLatin1();
    array1.resize(1);
    array1[0]=array0.at(0);
    sendstr+=array1.toHex();
    array1[0]=array0.at(1);
    sendstr+=array1.toHex();
    return sendstr;
}

QString FXProtocol::getReadHoldRegisterCommand(int startAddr, int length)
{
    //读D位地址
    QString sendstr="053030464657523044";
    sendstr+=addrNumStr(startAddr,length);
    //计算校验和
    QString strall=sendstr + computeSum(sendstr.mid(2));
    return strall;
}

QString FXProtocol::getReadCoilsRegisterCommand(int startAddr, int length)
{
    //读M位地址
    QString sendstr="05303046464252304d";
    //起始地址+数据长度
    sendstr+=addrNumStr(startAddr,length);
    //计算校验和
    QString strall=sendstr + computeSum(sendstr.mid(2));
    return strall;
}

QString FXProtocol::getWriteHoldRegisterCommand(int startAddr, int length, QList<ModbusValue> vData)
{
    //M位地址
    QString sendstr="053030464657573044";
    sendstr+=addrNumStr(startAddr, vData.size());
    //数据
    for (int i=0;i<vData.size();i++)
    {
        QString ss = QString("%1").arg(vData[i].valueI,4,16,QLatin1Char('0')).toUpper();
        for (int j = 0;j < ss.length();j++)
        {
            sendstr += QString("%1").arg(ss.at(j).toLatin1(),2,16,QLatin1Char('0'));
        }
    }
    //计算校验和
    QString strall=sendstr + computeSum(sendstr.mid(2));
    return strall;
}

QString FXProtocol::getWriteCoilsRegisterCommand(int startAddr, int length, QList<ModbusValue> vData)
{
    //M位地址
    QString sendstr="05303046464257304d";
    //起始地址+数据长度
    sendstr+=addrNumStr(startAddr, vData.size());
    //数据
    for (int i=0;i < vData.size();i++)
    {
        sendstr += QString("%1").arg(vData[i].valueI + 48, 2, 16, QLatin1Char('0'));
    }
    //计算校验和
    QString strall=sendstr + computeSum(sendstr.mid(2));
    return strall;
}

QString FXProtocol::computeSum(QString linkstring)
{
    QByteArray bytedata;
    bytedata=QByteArray::fromHex(linkstring.toLocal8Bit());
    int sunResult=0;
    for (int i=0;i<bytedata.size();i++)
    {
        sunResult+=(int)bytedata[i];
    }
    QString sumLastTwo=QString("%1").arg(sunResult,50,16,QLatin1Char('0')).right(2).toUpper();
    QString back;
    back=QString("%1").arg(sumLastTwo.at(0).toLatin1(),2,16,QLatin1Char('0'))
           +QString("%1").arg(sumLastTwo.at(1).toLatin1(),2,16,QLatin1Char('0'));
    return back;
}
void FXProtocol::onReceiveData(const QByteArray &data)
{
    if(data.at(0) == 0x02 && data.at(data.size()-3) == 0x03)
    {
        PLCRequestData dataRev = mCurDataRead;
        QByteArray valueArray = QByteArray::fromHex(data.mid(5, data.size() - 8));
//        QByteArray valueArray = data.mid(30);
        QList<ModbusValue> lstValue = dataRev.data;
        int index = 0;
        for(int i = 0; i < lstValue.size(); ++i){
            ValueType type = lstValue.at(i).valueType;
            if(type == VT_Bool){
                lstValue[i].valueI = valueArray.at(index);
                index += 1;
            } else if(type == VT_Int16){
                lstValue[i].valueI = byteArray2Int(valueArray.mid(index, 2));
                index += 2;
            } else if(type == VT_Int32){
                lstValue[i].valueDI = byteArray2Int(valueArray.mid(index, 4));
                index += 4;
            } else if(type == VT_Float){
                lstValue[i].valueF = byteArray2Float(valueArray.mid(index, 4));
                index += 4;
            }
        }
        dataRev.data = lstValue;
        emit sigData(dataRev);
        processData(dataRev);
    }
}
